/*!
 Temelia - generic data structures library written in C.

 Copyright (C) 2008, 2009 Ceata (http://ceata.org/proiecte/temelia).

 @author Dascalu Laurentiu

 This program is free software; you can redistribute it and
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version 3
 of the License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#ifndef COMMON_H_
#define COMMON_H_

#include "platform.h"

DECLSPEC extern int temelia_errno;

typedef enum
{
	NOT_EXCEPTION,

	MEMORY_ALLOCATION,

	NULL_POINTER,

	INVALID_INPUT,

	FULL,

	EMPTY,

	ELEMENT_NOT_FOUND
} Exceptions;

#ifndef MAX
#define MAX(A,B)                    ((A)>(B)?(A):(B))
#endif

#ifndef MIN
#define MIN(A,B)                    ((A)<(B)?(A):(B))
#endif

#define DEFAULT_SIZE                (64)
#define TEMELIA_INFINITY            (1.7976931348623157e+308)

/*!
 * @brief Allocator, returns a pointer to a memory address with size bytes allocated.
 * @param Memory size.
 * It's a wrapper over malloc function, included in CRT.
 */
DECLSPEC INLINE void *_new(int size);

/*!
 * @brief Reallocator, returns a pointer to a memory address with size bytes allocated;
 * it requires the old pointer.
 * @param old pointer.
 * @param new size.
 * It's a wrapper over realloc function, included in CRT.
 */
DECLSPEC INLINE void *_realloc(void *old_addr, int size);

/*!
 * @brief Deallocator, frees allocated memory.
 * @param Pointer to be freed.
 * It's a wrapper over free function, included in CRT.
 */
DECLSPEC INLINE void _delete(void *memory_address);

/*!
 * @brief Compares two pointers after their address. It's used to find memory addresses in
 * a data structure.
 * @param First memory address.
 * @param Second memory address.
 */
DECLSPEC INLINE int compare_pointers(void *x, void *y, void *context);

/*
 * @brief Random number wrapper generator over standard rand() function.
 */
DECLSPEC INLINE int _rand();

DECLSPEC void report_error(CONST char *RESTRICT _format, ...);

/*!
 * @brief Initialization and destruction functions.
 */
DECLSPEC void temelia_init();
DECLSPEC void temelia_finish();

/*!
 * Logging functions; default output stream is = stdout =
 * LOGGER is a simple wrapper over standard fprintf function
 */
DECLSPEC void _logger_init(void *output_stream);
DECLSPEC void _logger_log(CONST char *RESTRICT _format, ...);
DECLSPEC void _logger_destroy();

/*!
 * Empty handlers
 */
DECLSPEC void _empty_init(void *output_stream);
DECLSPEC void _empty_log(CONST char *RESTRICT _format, ...);
DECLSPEC void _empty_destroy();

#define LOGGING

// Logging support macros
#ifdef LOGGING
#define INIT         _logger_init
#define LOGGER       _logger_log
#define DESTROY      _logger_destroy
#else
#define INIT         _empty_init
#define LOGGER       _empty_log
#define DESTROY      _empty_destroy
#endif /* LOGGING */

/*
 * @brief Assertion macro. It uses the do { ... } while(0) construct because I want
 * to force the user to put ";" after the macro invocation.
 * In RELEASE, comment the lines between do and while.
 */
#define _ASSERT(ITEM, OPERATION, LIMIT_VALUE, ERROR_VALUE, RETURN_VALUE) \
	do \
	{\
		if (ITEM OPERATION LIMIT_VALUE)\
		{\
			if (ERROR_VALUE != NOT_EXCEPTION)\
				LOGGER("assertion failed on (file, line) (%s, %d)\n",\
					__FILE__, __LINE__);\
			temelia_errno = ERROR_VALUE;\
			return RETURN_VALUE;\
		}\
	} while(0)\

#endif /* COMMON_H */
